package com.fourfaith.iot.beidou.listener;

import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import com.fourfaith.common.pojo.ResultDto;
import com.fourfaith.iot.beidou.decodec.BeiDouContants;
import com.fourfaith.iot.beidou.decodec.BeiDouEncoder;
import com.fourfaith.iot.beidou.manager.SerialPortManager;
import com.fourfaith.iot.beidou.message.inbound.BDfkiMessage;
import com.fourfaith.iot.beidou.message.inbound.BDtciMessage;
import com.fourfaith.iot.beidou.utils.MessageParseUtil;
import com.fourfaith.iot.device.cloud.access.dubbo.pojo.param.BeiDouParam;
import com.fourfaith.iot.device.cloud.access.dubbo.service.IBeidouDubboService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Locale;

/**
 * 北斗解析和队列下发
 *
 * @author shiyunan
 */
@Service
@Slf4j
public class BeiDouListenerImpl implements SerialPortDataListener {

    private StringBuilder buffer = new StringBuilder(); // 缓冲区，用于存储接收到的数据
    private boolean startMarkerFound = false; // 标记开始字符是否找到
    private boolean endMarkerFound = false; // 标记结束字符是否找到

    @Resource
    private SerialPortManager serialPortManager;


    @DubboReference(timeout = 10000)
    private IBeidouDubboService beidouDubboService;

    @Override
    public int getListeningEvents() {
        return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
    }

    @Override
    public void serialEvent(SerialPortEvent event) {
        if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
            return;
        }
        try {
            int available = serialPortManager.getSerialPort().bytesAvailable(); // 获取可读取的字节数
            byte[] data = new byte[available];
            int bytesRead = serialPortManager.getSerialPort().readBytes(data, available); // 读取数据
            handleData(data, bytesRead);
        } catch (Exception e) {
            log.error("serialEvent error:{}", e);
        }


    }

    /**
     * 处理数据
     *
     * @param data
     * @param bytesRead
     */
    private synchronized void handleData(byte[] data, int bytesRead) {
        for (int i = 0; i < bytesRead; i++) {
            char ch = (char) data[i];

            // 检查开始标记 '$'开始
            if (!startMarkerFound && ch == (byte) 0x24) {
                startMarkerFound = true;
                buffer.setLength(0); // 清空缓冲区
                buffer.append(ch);
            }
            // 回车换行结束
            else if (startMarkerFound && ch == (byte) 0x0A) {
                endMarkerFound = true;
                buffer.append(ch);
                processCompletePacket(buffer.toString());
                startMarkerFound = false;
                endMarkerFound = false;
                buffer.setLength(0); // 清空缓冲区
            } else if (startMarkerFound) {
                buffer.append(ch);
            }
        }
    }

    /**
     * 处理有效完整的数据包
     *
     * @param packet
     */
    private void processCompletePacket(String packet) {
        // 处理完整的数据包
        if (packet.contains(BeiDouContants.checkFlag)) { // ASCII码 包含*的有效报文
            log.info("Received complete packet: " + packet);
            Object object = BeiDouEncoder.decode(packet);
            if (object != null) {
                if(object instanceof BDtciMessage){
                    BDtciMessage bDtciMessage = (BDtciMessage) object;
                    log.info("接收到报文通信信息:{}", bDtciMessage);
                    BeiDouParam beiDouParam = new BeiDouParam();
                    beiDouParam.setVersion(BeiDouContants.BEI_DOU3);
                    String data = bDtciMessage.getData();
                    if(StringUtils.isNotBlank(data)){
                        data = data.substring(2);
                        beiDouParam.setMessageContext(data);
                        // 水文协议
                        if(data.toUpperCase(Locale.ROOT).startsWith("7E7E")){
                            beiDouParam.setProtocol(BeiDouContants.PROTOCOL_HYDROLOGICAL);
                        }
                        // 广播协议
                        else if(data.toUpperCase(Locale.ROOT).startsWith("7E") && data.toUpperCase(Locale.ROOT).endsWith("7E")){
                            beiDouParam.setProtocol(BeiDouContants.PROTOCOL_BROADCASTL);
                        }
                    }
                    beiDouParam.setFunctionCode(bDtciMessage.getCommand());
                    beiDouParam.setReceivedId(bDtciMessage.getAcceptorNumber());
                    beiDouParam.setSendId(bDtciMessage.getSenderNumber());
                    forwardMessage(beiDouParam);
                }else if(object instanceof BDfkiMessage){
                    MessageParseUtil.setSendResult((BDfkiMessage) object);
                }
            }
        }
    }


    private void forwardMessage(BeiDouParam beidouParam) {
        if (beidouParam == null) {
            return;
        }
        try {
            ResultDto<Boolean> result = beidouDubboService.receive(beidouParam);
            log.info("北斗消息推送服务器：{}", result);
        } catch (Exception e) {
            log.info("推送失败：{}", e.getMessage(), e);
        }
    }
}
